﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geoprocessor;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.DataManagementTools;
using ESRI.ArcGIS.Analyst3DTools;

namespace DemFromTIN
{
    class Program
    {
        [DllImport("ole32.dll")]
        private static extern void CoInitialize(IntPtr pvReserved);
        [DllImport("ole32.dll")]
        private static extern void CoUninitialize();

        static void Main(string[] args)
        {
            CoInitialize(IntPtr.Zero);

            try
            {
                Console.WriteLine("=== TIN 转 DEM 工具 (ArcEngine 10.x) ===");

                if (!InitializeLicense())
                {
                    Console.WriteLine("许可证初始化失败！");
                    return;
                }

                // 用户输入
                Console.Write("输入 TIN 数据路径（如：C:\\data\\terrain.tin）：");
                string inputTIN = Console.ReadLine();
                Console.Write("输出 DEM 栅格路径（如：C:\\output\\dem.tif）：");
                string outputRaster = Console.ReadLine();
                Console.Write("设置像元大小（米）：");
                double cellSize = double.Parse(Console.ReadLine());

                // 生成 DEM
                if (GenerateDEMfromTIN(inputTIN, outputRaster, cellSize))
                {
                    Console.WriteLine($"\n成功生成 DEM: {outputRaster}");
                }
                else
                {
                    Console.WriteLine("\nDEM 生成失败！");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发生错误：{ex.Message}\n{ex.StackTrace}");
            }
            finally
            {
                CoUninitialize();
                Console.WriteLine("\n按任意键退出...");
                Console.ReadKey();
            }
        }

        private static bool InitializeLicense()
        {
            IAoInitialize aoInit = new AoInitializeClass();
            esriLicenseStatus status = aoInit.Initialize(esriLicenseProductCode.esriLicenseProductCodeEngineGeoDB);

            if (status != esriLicenseStatus.esriLicenseCheckedOut)
            {
                Console.WriteLine("无法获取 ArcEngine 基础许可");
                return false;
            }

            if (aoInit.IsExtensionCodeAvailable(
                esriLicenseProductCode.esriLicenseProductCodeEngineGeoDB,
                esriLicenseExtensionCode.esriLicenseExtensionCode3DAnalyst) != esriLicenseStatus.esriLicenseAvailable)
            {
                Console.WriteLine("3D Analyst 扩展不可用");
                return false;
            }

            aoInit.CheckOutExtension(esriLicenseExtensionCode.esriLicenseExtensionCode3DAnalyst);
            Console.WriteLine("许可证初始化成功 (含 3D Analyst)");
            return true;
        }

        private static bool GenerateDEMfromTIN(string tinPath, string outputRasterPath, double cellSize)
        {
            Geoprocessor gp = new Geoprocessor { OverwriteOutput = true };

            try
            {
                if (!Directory.Exists(tinPath))
                {
                    Console.WriteLine("❌ 错误：TIN 输入路径不存在，必须是一个文件夹！");
                    return false;
                }

                if (!outputRasterPath.EndsWith(".tif", StringComparison.OrdinalIgnoreCase))
                    outputRasterPath += ".tif";

                // 构造参数（按顺序）
                IVariantArray parameters = new VarArrayClass();
                parameters.Add(tinPath);                          // 输入 TIN
                parameters.Add(outputRasterPath);                 // 输出栅格路径
                parameters.Add("FLOAT");                          // 输出值类型
                parameters.Add("LINEAR");                         // 插值方法
                parameters.Add("CELLSIZE");                       // 采样类型
                parameters.Add(cellSize.ToString());              // 单元格大小

                // 执行 TinToRaster 工具（注意大小写）
                IGeoProcessorResult result = gp.Execute("TinToRaster", parameters, null) as IGeoProcessorResult;

                // 输出消息
                Console.WriteLine("\n地理处理消息：");
                for (int i = 0; i < gp.MessageCount; i++)
                {
                    Console.WriteLine(gp.GetMessage(i));
                }

                return result?.Status == esriJobStatus.esriJobSucceeded;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"❌ 执行失败：{ex.Message}");
                return false;
            }
            finally
            {
                Marshal.FinalReleaseComObject(gp);
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }
    }
}
